package com.hz.qs.service;

import cn.hutool.core.util.IdUtil;
import com.hz.qs.dao.CheckGuideDao;
import com.hz.qs.dao.CustomerDao;
import com.hz.qs.dao.CustomerDetailDao;
import com.hz.qs.dao.DoctorDao;
import com.hz.qs.model.*;
import com.hz.qs.model.view.ExaminerequestBz;
import com.hz.qs.model.vo.CustomerDataVo;
import com.hz.qs.model.vo.CustomerRequest;
import com.hz.qs.model.vo.RequestChangeVo;
import com.hz.qs.utils.RestResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.hz.qs.utils.Common.*;


@Service
@Slf4j
public class CustomerService {

    @Autowired
    private CustomerDao customerDao;

    @Autowired
    private CheckGuideDao checkGuideDao;

    @Autowired
    private DoctorDao doctorDao;

    @Autowired
    private CustomerDetailDao customerDetailDao;

    @Autowired
    private CoreService coreService;


    /**
     * 客户列表对外函数
     *
     * @param customerRequest
     * @return com.hz.qs.utils.RestResult
     * @author yejy
     * @date 2020/11/4 22:16
     */
    public RestResult getCustomerList(CustomerRequest customerRequest) {
        Map<String, Object> map = new HashMap<>(2);
        LinkedList<Map<String, Object>> queueList = new LinkedList<>();
        LinkedList<Map<String, Object>> queues = coreService.groupByQueues(customerRequest);
        List<CustomerDataVo> list = coreService.getCustomersList(customerRequest);
        Map<String, List<CustomerDataVo>> idmap = list.stream().collect(Collectors.groupingBy(CustomerDataVo::getQueueId));
        idmap.forEach((k, v) -> {
            Map<String, Object> qmap = new HashMap<>(2);
            List<CustomerDataVo> collect = v.stream().filter(f -> f.getQueueId().equals(k)).distinct().sorted(Comparator.comparing(CustomerDataVo::getOrderNo)).collect(Collectors.toList());
            qmap.put("queueName", v.stream().findAny().map(CustomerDataVo::getQueueName).orElse(""));
            qmap.put("customerQueueData", collect);
            queueList.add(qmap);
        });
        map.put("customerData", queueList);
        map.put("queueData", queues);
        return RestResult.successResult(map);
    }

    /**
     * 获取客户列表中间的检查项目队列
     *
     * @param customerDatas
     * @return java.util.LinkedList<java.lang.String>
     * @author yejy
     * @date 2020/11/4 22:15
     */
    private LinkedList<String> getCheckQueues(List<ExaminerequestBz> customerDatas) {
        LinkedList<String> queueList = new LinkedList<>();
        Map<String, List<ExaminerequestBz>> queueMap = customerDatas.stream().collect(Collectors.groupingBy(ExaminerequestBz::getZLJFJC));
        queueMap.forEach((k, v) -> queueList.add(k + "(" + v.size() + ")"));
        return queueList;
    }

    /**
     * 03 根据客户ID获取检查项目数据
     *
     * @param customerId
     * @param currentDate
     * @return com.hz.qs.utils.RestResult
     * @author yejy
     * @date 2020/11/8 13:46
     */
    public List<YiQueues> getCheckProjectsByCustomerId(String customerId, String currentDate) {
        LinkedList<YiQueues> projects = customerDao.getCheckProjectsByCustomerId(customerId);
        List<YiQueues> currentList = customerDao.getCurrentDateQueues(currentDate + START_TIME, currentDate + END_TIME);
        Map<String, List<YiQueues>> groupByProjectMap = currentList.stream().filter(f -> f.getState().equals(QUEUE_STATE_QIAN_DAO)).collect(Collectors.groupingBy(YiQueues::getProjectId));
        groupByProjectMap.forEach((k, v) -> {
            List<String> sortByQueueCustomerIds = v.stream().sorted(Comparator.comparing(YiQueues::getOrderNo)).map(m -> m.getCustomerId() + "#" + m.getWasteTime()).distinct().collect(Collectors.toList());
            for (int i = 0; i < sortByQueueCustomerIds.size(); i++) {
                int tmp = i;
                if (sortByQueueCustomerIds.get(tmp).split("#")[0].equals(customerId)) {
                    projects.stream().filter(f -> f.getProjectId().equals(k)).forEach(m -> {
                        m.setWaitPeople(tmp);
                        m.setWaitTime(tmp * Integer.parseInt(sortByQueueCustomerIds.get(tmp).split("#")[1]));
                    });
                }
            }
        });
        return projects.stream().map(m -> {
            Integer orElse = Optional.ofNullable(m.getWaitTime()).orElse(0);
            m.setWaitTime(orElse);
            return m;
        }).sorted(Comparator.comparing(YiQueues::getWaitTime)).collect(Collectors.toList());
    }

    /**
     * 03 调整申请
     *
     * @param yiReqChange
     * @return java.lang.Integer
     * @author yejy
     * @date 2020/11/8 15:55
     */
    @Transactional
    public Integer addRequestChange(YiReqChange yiReqChange) {
        yiReqChange.setChangeId(IdUtil.simpleUUID());
        return customerDao.addRequestChange(yiReqChange);
    }

    /**
     * 03 放弃检查
     *
     * @param customerId
     * @param currentDate
     * @return java.lang.Integer
     * @author yejy
     * @date 2020/11/8 15:55
     */
    @Transactional
    public Integer cancelCheck(String customerId, String id, String currentDate) {
        YiQueues queuesById = customerDao.getQueuesById(id);
        if (queuesById.getState() > QUEUE_STATE_QIAN_DAO) {
            return -2;
        } else {
            String firstDate = currentDate + START_TIME;
            String endDate = currentDate + END_TIME;
            customerDao.cancelCheck_queue(id, 8);
            LinkedList<YiQueues> queuesData = customerDao.getYiQueuesData(customerId, firstDate, endDate);
            boolean allMatch = queuesData.stream().allMatch(m -> m.getState().equals(QUEUE_STATE_JIAN_CHA));
            if (allMatch) {
                return customerDao.cancelCheck(customerId, 8);
            }
            return 0;
        }
    }

    /**
     * 21 调整申请展示列表
     *
     * @param
     * @return com.hz.qs.utils.RestResult
     * @author yejy
     * @date 2020/11/8 16:25
     */
    public RestResult getRequestChangeList() {
        List<RequestChangeVo> list = customerDao.getRequestChangeList();
        return RestResult.successResult(list);
    }

    /**
     * 06 客户详情展示
     *
     * @param customerId
     * @param currentDate
     * @return com.hz.qs.utils.RestResult
     * @author yejy
     * @date 2020/11/8 17:17
     */
    @Transactional
    public RestResult getCustomerDetail(String customerId, String currentDate) {
        List<YiCustomerDetail> list = customerDetailDao.getCustomerDetail(customerId);
        if (list.size() == 0) {
            String firstDate = currentDate + START_TIME;
            String endDate = currentDate + END_TIME;
            List<CustomerDataVo> customerDataVos = customerDao.getCustomerDataByExamQuest(customerId, firstDate, endDate);
            if (customerDataVos.size() > 0) {
                customerDetailDao.insertCustomerDetail(customerDataVos.get(0));
                List<YiCustomerDetail> nlist = customerDetailDao.getCustomerDetail(customerDataVos.get(0).getCustomerId());
                return RestResult.successResult(nlist);
            } else {
                return RestResult.failResult("没有找到客户信息！！", 500);
            }
        }
        return RestResult.successResult(list);
    }

    /**
     * 07 客户详情编辑
     *
     * @param customerDetail
     * @return java.lang.Integer
     * @author yejy
     * @date 2020/11/8 19:29
     */
    @Transactional
    public Integer editCustomerDetail(YiCustomerDetail customerDetail) {
        return customerDetailDao.updateByPrimaryKeySelective(customerDetail);
    }

    /**
     * 08 健管师客户列表
     *
     * @param jgsId
     * @param currentDate
     * @param state
     * @return com.hz.qs.utils.RestResult
     * @author yejy
     * @date 2020/11/8 19:29
     */
    public RestResult getAllCustomerData(String jgsId, String currentDate, String state) {
        String stateStr = Optional.ofNullable(state).filter(m -> !"null".equals(m)).orElse("");
        String firstDate = currentDate + START_TIME;
        String endDate = currentDate + END_TIME;
        List<CustomerDataVo> list = customerDao.getAllCustomerData(jgsId, firstDate, endDate, stateStr);
        return RestResult.successResult(list);
    }

    /**
     * 10 体检导检单展示
     *
     * @param checkId
     * @param currentDate
     * @param customerId
     * @return com.hz.qs.utils.RestResult
     * @author yejy
     * @date 2020/11/24 15:04
     */
    @Transactional
    public RestResult getCheckGuideData(String checkId, String currentDate, String customerId) {
        List<YiCheckGuide> guideList = checkGuideDao.getCheckGuideData(checkId);
        String firstDate = currentDate + START_TIME;
        String endDate = currentDate + END_TIME;
        List<CustomerDataVo> customerDataVos = customerDao.getCustomerDataByExamQuest(customerId, firstDate, endDate);
        if (guideList.size() == 0) {
            checkGuideDao.insertCheckGuide(customerDataVos.get(0));
        }
        if (customerDataVos.size() > 0) {
            List<Map<String, Object>> projectData = new ArrayList<>();
            Map<String, Object> dataMap = new HashMap<>(2);
            List<YiCheckGuide> nlist = checkGuideDao.getCheckGuideData(customerDataVos.get(0).getCheckId());
            Map<String, List<CustomerDataVo>> collect = customerDataVos.stream().collect(Collectors.groupingBy(CustomerDataVo::getXmlxName));
            collect.forEach((k, v) -> {
                Map<String, Object> map = new HashMap<>(2);
                map.put("projectTypeName", k);
                map.put("projectTypeData", v);
                projectData.add(map);
            });
            dataMap.put("checkData", nlist);
            dataMap.put("projectData", projectData);
            return RestResult.successResult(dataMap);
        } else {
            return RestResult.failResult("没有找到客户信息！！", 500);
        }
    }

    /**
     * 11 编辑体检导检单
     *
     * @param guide
     * @return java.lang.Integer
     * @author yejy
     * @date 2020/11/24 15:04
     */
    @Transactional
    public Integer editCheckGuide(YiCheckGuide guide) {
        return checkGuideDao.updateByPrimaryKeySelective(guide);
    }

    /**
     * 轮询获取叫号信息
     *
     * @param jgsId
     * @param currentDate
     * @return com.hz.qs.utils.RestResult
     * @author yejy
     * @date 2020/11/26 14:21
     */
    public RestResult loopTips(String jgsId, String currentDate) {
        String sDate = currentDate + START_TIME;
        String eDate = currentDate + END_TIME;
        return RestResult.successResult(doctorDao.loopTips(jgsId, sDate, eDate, CALL_ING));
    }

    /**
     * 健管师确认医生叫号
     *
     * @param id
     * @return com.hz.qs.utils.RestResult
     * @author yejy
     * @date 2021/1/19 13:52
     */
    @Transactional
    public RestResult confirmCall(String id) {
        YiCallPatient yiCallPatient = doctorDao.selectByPrimaryKey(id);
        Integer callState = yiCallPatient.getCallState();
        if (callState.equals(CALL_ING)) {
            YiCallPatient callPatient = new YiCallPatient();
            callPatient.setId(id);
            callPatient.setCallState(JGS_CONFIRM);
            doctorDao.updateByPrimaryKeySelective(callPatient);
            doctorDao.updateQueueState(yiCallPatient);
            return RestResult.successResult(null);
        } else if (callState.equals(DOC_CANCEL)) {
            return RestResult.failResult("医生取消了叫号！！！", 4001);
        } else if (callState.equals(DOC_CONFIRM)) {
            return RestResult.successResult("医生已经确认，请尽快就诊！！");
        }
        return RestResult.failResult("异常，请和管理员联系！！！" + id, 500);
    }

    /**
     * 上移下移函数
     *
     * @param id
     * @param type
     * @param currentDate
     * @return com.hz.qs.utils.RestResult
     * @author yejy
     * @date 2021/1/19 13:54
     */
    @Transactional
    public synchronized RestResult UpOrDown2(String id, String type, String currentDate) {
        String sDate = currentDate + START_TIME;
        String eDate = currentDate + END_TIME;
        final double sub = 1.001d;
        //获取页面上选中的项目
        YiQueues bQueue = customerDao.getQueuesById(id);
        Double bOrderNo = bQueue.getOrderNo();
        LinkedList<YiQueues> customerList = doctorDao.getYiQueuesByCustomerId(bQueue.getCustomerId());
        LinkedList<YiQueues> queueDataByQueueIdList = doctorDao.getYiQueuesByQueueId(sDate, eDate, bQueue.getQueueId());
        if (UP.equals(type)) {
            for (int i = 0; i < queueDataByQueueIdList.size(); i++) {
                if (queueDataByQueueIdList.get(i).getCustomerId().equals(bQueue.getCustomerId())) {
                    if (i - 1 > 0) {
                        //获取页面点击的项目的当前客户的上一个是谁
                        YiQueues upQueue = queueDataByQueueIdList.get(i - 1);
                        List<YiCallPatient> callPatientList = doctorDao.getCallDataByCustomerIdAndQeueuId(upQueue.getCustomerId(), upQueue.getQueueId());
                        if (upQueue.getState().equals(QUEUE_STATE_QIAN_DAO) && callPatientList.size() == 0) {
                            bQueue.setOrderNo(bOrderNo - sub);
                            doctorDao.updateQueue(bQueue);
                            break;
                        } else {
                            return RestResult.failResult("不允许状态不为已预约或者已叫号的客户上移！！", 500);
                        }
                    } else {
                        return RestResult.failResult("为防止医生叫号列表没有刷新，最多只能上移到第2位！", 500);
                    }
                }
            }
            //获取该客户顺序项目中页面点击项目的上一个
            Double maxOrderNo = customerList.stream().max(Comparator.comparing(YiQueues::getOrderNo)).map(YiQueues::getOrderNo).orElse(9999.000d);
            for (int i = 0; i < customerList.size(); i++) {
                if (customerList.get(i).getQueueId().equals(bQueue.getQueueId())) {
                    if (bQueue.getOrderNo() < maxOrderNo) {
                        YiQueues upQueue2 = customerList.get(i + 1);
                        List<YiCallPatient> callPatientList = doctorDao.getCallDataByCustomerIdAndQeueuId(upQueue2.getCustomerId(), upQueue2.getQueueId());
                        if (upQueue2.getState().equals(QUEUE_STATE_QIAN_DAO) && callPatientList.size() == 0) {
                            upQueue2.setOrderNo(bOrderNo + sub);
                            doctorDao.updateQueue(upQueue2);
                            break;
                        } else {
                            return RestResult.failResult("不允许状态不为已预约或者已叫号的客户上移！！", 500);
                        }
                    } else {
                        return RestResult.failResult("为防止医生叫号列表没有刷新，最多只能上移到第2位！", 500);
                    }
                }
            }
        } else if (DOWN.equals(type)) {
            Double maxOrderNo = queueDataByQueueIdList.stream().max(Comparator.comparing(YiQueues::getOrderNo)).map(YiQueues::getOrderNo).orElse(9999.000d);
            for (int i = 0; i < queueDataByQueueIdList.size(); i++) {
                if (queueDataByQueueIdList.get(i).getCustomerId().equals(bQueue.getCustomerId())) {
                    if (bQueue.getOrderNo() < maxOrderNo) {
                        //获取页面点击的项目的当前客户的上一个是谁
                        YiQueues downQueue = queueDataByQueueIdList.get(i + 1);
                        List<YiCallPatient> callPatientList = doctorDao.getCallDataByCustomerIdAndQeueuId(downQueue.getCustomerId(), downQueue.getQueueId());
                        if (downQueue.getState().equals(QUEUE_STATE_QIAN_DAO) && callPatientList.size() == 0) {
                            bQueue.setOrderNo(bQueue.getOrderNo() + sub);
                            doctorDao.updateQueue(bQueue);
                            break;
                        } else {
                            return RestResult.failResult("不允许状态不为已预约或者已叫号的客户下移！！", 500);
                        }
                    } else {
                        return RestResult.failResult("已经是最后一位，不允许下移！！", 500);
                    }
                }
            }
            //获取该客户顺序项目中页面点击项目的上一个
            for (int i = 0; i < customerList.size(); i++) {
                if (customerList.get(i).getQueueId().equals(bQueue.getQueueId())) {
                    if (i - 1 > 0) {
                        YiQueues downQueue2 = customerList.get(i - 1);
                        List<YiCallPatient> callPatientList = doctorDao.getCallDataByCustomerIdAndQeueuId(downQueue2.getCustomerId(), downQueue2.getQueueId());
                        if (downQueue2.getState().equals(QUEUE_STATE_QIAN_DAO) && callPatientList.size() == 0) {
                            downQueue2.setOrderNo(bQueue.getOrderNo() - sub);
                            doctorDao.updateQueue(downQueue2);
                            break;
                        } else {
                            return RestResult.failResult("不允许状态不为已预约或者已叫号的客户下移！！", 500);
                        }
                    } else {
                        return RestResult.failResult("为防止医生叫号列表没有刷新，最多只能上移到第2位！", 500);
                    }
                }
            }
        } else {
            return RestResult.failResult("type异常！！！" + type, 500);
        }
        return RestResult.successResult(null);
    }

    @Transactional(rollbackFor = Exception.class)
    public RestResult upOrDownForQueueCustomer(String queueId, String customerId, String type, String currentDate) {
        String sDate = currentDate + START_TIME;
        String eDate = currentDate + END_TIME;
        LinkedList<YiQueues> queueDataByQueueIdList = doctorDao.getYiQueuesByQueueId(sDate, eDate, queueId);
        if (UP.equals(type)) {
            for (int i = 0; i < queueDataByQueueIdList.size(); i++) {
                if (queueDataByQueueIdList.get(i).getCustomerId().equals(customerId)) {
                    if (i - 1 > 0) {
                        YiQueues upQueue = queueDataByQueueIdList.get(i - 1);
                        Double selectOrderNo = queueDataByQueueIdList.get(i).getOrderNo();
                        Double upOrderNo = upQueue.getOrderNo();
                        List<YiCallPatient> callPatientList = doctorDao.getCallDataByCustomerIdAndQeueuId(upQueue.getCustomerId(), upQueue.getQueueId());
                        if (upQueue.getState().equals(QUEUE_STATE_QIAN_DAO) && callPatientList.size() == 0) {
                            queueDataByQueueIdList.get(i).setOrderNo(upOrderNo);
                            doctorDao.updateQueue(queueDataByQueueIdList.get(i));
                            upQueue.setOrderNo(selectOrderNo);
                            doctorDao.updateQueue(upQueue);
                            return RestResult.successResult(null);
                        } else {
                            return RestResult.failResult("不允许状态不为已预约或者已叫号的客户上移！！", 5001);
                        }
                    } else {
                        return RestResult.failResult("为防止医生叫号列表没有刷新，最多只能上移到第2位！", 5002);
                    }
                }
            }
        } else if (DOWN.equals(type)) {
            for (int i = 0; i < queueDataByQueueIdList.size(); i++) {
                if (queueDataByQueueIdList.get(i).getCustomerId().equals(customerId)) {
                    if (i + 1 < queueDataByQueueIdList.size()) {
                        Double selectOrderNo = queueDataByQueueIdList.get(i).getOrderNo();
                        YiQueues downQueue = queueDataByQueueIdList.get(i + 1);
                        Double downOrderNo = downQueue.getOrderNo();
                        List<YiCallPatient> callPatientList = doctorDao.getCallDataByCustomerIdAndQeueuId(downQueue.getCustomerId(), downQueue.getQueueId());
                        if (downQueue.getState().equals(QUEUE_STATE_QIAN_DAO) && callPatientList.size() == 0) {
                            downQueue.setOrderNo(selectOrderNo);
                            doctorDao.updateQueue(downQueue);
                            queueDataByQueueIdList.get(i).setOrderNo(downOrderNo);
                            doctorDao.updateQueue(queueDataByQueueIdList.get(i));
                            return RestResult.successResult(null);
                        } else {
                            return RestResult.failResult("不允许状态不为已预约或者已叫号的客户下移！！", 500);
                        }
                    } else {
                        return RestResult.failResult("已经是最后一位，不允许下移！！", 500);
                    }
                }
            }
        } else {
            return RestResult.failResult("type异常！！！" + type, 500);
        }
        return RestResult.failResult("没有找到该客户，或者状态异常，不允许移动！！", 4001);
    }
}
